﻿using MikuMikuLibrary.Archives;
using MikuMikuLibrary.Archives.Farc;
using MikuMikuLibrary.IO;
using MikuMikuLibrary.Sprites;
using MikuMikuLibrary.Textures;
using MikuMikuModel.Logs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ft_module_parser
{
    class BC5Begone
    {
        public static int quality = 2;
        public static void Process(String newpath, String filePath, int quality = 2, bool replace = false)
        {
            if (!replace)
                if (File.Exists(newpath + "\\" + Path.GetFileName(filePath)))
                    return;
            GC.Collect();
            Logs.WriteLine("Processing " + filePath);
            string farcpath = filePath;

            var spriteset = new SpriteSet();
            string handle;
            using (var farcArchive = BinaryFile.Load<FarcArchive>(farcpath))
            using (var entryStream = farcArchive.Open(farcArchive.Entries.First(), EntryStreamMode.MemoryStream))
            {
                spriteset.Load(entryStream);
                handle = farcArchive.Entries.First();
            }

            List<Texture> newtex = new List<Texture>();

            foreach (var i in spriteset.TextureSet.Textures)
            {
                //if (i.IsYCbCr)
                {
                    var bitmap = TextureDecoder.Decode(i);
                    if(quality == 1)
                    {
                        var anew = TextureEncoder.Encode(bitmap, TextureFormat.DXT5, false);
                        anew.Id = i.Id;
                        newtex.Add(anew);
                    } else
                    {
                        var anew = TextureEncoder.Encode(bitmap, TextureFormat.RGBA, false);
                        anew.Id = i.Id;
                        newtex.Add(anew);
                    }
                } //else { newtex.Add(i); }
            }

            spriteset.TextureSet.Textures.Clear();

            foreach (var i in newtex)
            {
                spriteset.TextureSet.Textures.Add(i);
            }

            MemoryStream memoryStream = new MemoryStream();

            spriteset.Save(memoryStream, true);

            FarcArchive newfarc = new FarcArchive();
            newfarc.IsCompressed = true;
            newfarc.Add(handle, memoryStream, true);
            newfarc.Save(newpath + "\\" + Path.GetFileName(filePath));
        }

        public static void Process(string[] args)
        {
            Thread.CurrentThread.Priority = ThreadPriority.Lowest;

            Console.WriteLine("BC5Begone v0.2");
            Console.WriteLine("");
            Console.WriteLine("Select quality :");
            Console.WriteLine("1. DXT5 (Low)");
            Console.WriteLine("2. RGBA (High)");
            int iquality;
            bool isSelected = false;

            while (!isSelected)
            {
                try
                {
                    Console.Write("Select Quality > ");
                    iquality = int.Parse(Console.ReadLine());
                    if ((iquality == 1) || (iquality == 2))
                        isSelected = true;
                    quality = iquality;
                }
                catch
                {

                }
            }

            string path = @"rom\2d";
            string newpath = @"mdata\M999\rom\2d";
            string gamepath = "";

            if (!Directory.Exists(gamepath + "mdata\\M999"))
                Directory.CreateDirectory(gamepath + "mdata\\M999");

            if (!Directory.Exists(gamepath + "mdata\\M999\\rom"))
                Directory.CreateDirectory(gamepath + "mdata\\M999\\rom");

            if (!Directory.Exists(gamepath + "mdata\\M999\\rom\\2d"))
                Directory.CreateDirectory(gamepath + "mdata\\M999\\rom\\2d");

            if (!File.Exists(gamepath + "mdata\\M999\\info.txt"))
                File.WriteAllText(gamepath + "mdata\\M999\\info.txt", "#mdata_info\ndepend.length=0\nversion=20161030\n");

            string[] filespl = System.IO.Directory.GetFiles("rom\\2d\\", "*.farc");

            var files = filespl.ToList();

            Parallel.ForEach(files, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, (filePath) =>
            {
                Process(newpath, filePath, quality, false);
            });

            try
            {
                var list = mdataUtilities.getMdatas("mdata\\");

                foreach (var i in list)
                {
                    if (Directory.Exists("mdata\\M" + string.Format("{0:000}", i) + "\\rom\\2d\\"))
                    {
                        if (i != 999)
                        {
                            var lefiles = Directory.GetFiles("mdata\\M" + string.Format("{0:000}", i) + "\\rom\\2d\\", "*.farc");
                            Parallel.ForEach(lefiles, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, (filePath) =>
                            {
                                Process(newpath, filePath, quality, true);
                            });
                        }
                    }
                }
            }
            catch (Exception Ex)
            {
                Console.WriteLine("no mdata?");
            }
        }
    }
}
